package com.easy.mongodb.core.conditions.query;

import cn.hutool.core.lang.Assert;
import com.easy.mongodb.common.params.SFunction;
import com.easy.mongodb.common.utils.ArrayUtils;
import com.easy.mongodb.core.biz.TableFieldInfo;
import com.easy.mongodb.core.conditions.AbstractLambdaWrapper;
import com.easy.mongodb.core.toolkit.FieldUtils;
import com.easy.mongodb.core.toolkit.TableInfoHelper;
import com.mongodb.client.model.Projections;

import java.util.Arrays;
import java.util.function.Predicate;

/**
 * ProjectName: easy-mongodb
 * Description: Lambda 语法使用 Wrapper
 * Author: vapeshop
 * Date: 2022/7/11 14:04:55
 * UpdateUser: vapeshop
 * UpdateDate: 2022/7/11 14:04:55
 * UpdateRemark: The modified content
 * Version: 1.0
 * <p>
 * Copyright © 2022 vapeshop Technologies Inc. All Rights Reserved
 **/
@SuppressWarnings("serial")
public class LbqWrapper<T> extends AbstractLambdaWrapper<T, LbqWrapper<T>>
        implements Query<LbqWrapper<T>, T, SFunction<T, ?>> {
    /**
     * 从第多少条开始查询
     */
    protected Integer from;
    /**
     * 查询多少条记录
     */
    protected Integer size;

    public LbqWrapper() {
        this((T) null);
    }

    public LbqWrapper(T entity) {
        super.setEntity(entity);
        super.initNeed();
    }

    public LbqWrapper(Class<T> entityClass) {
        super.setEntityClass(entityClass);
        super.initNeed();
    }

    LbqWrapper(T entity, Class<T> entityClass) {
        super.setEntity(entity);
        super.setEntityClass(entityClass);
    }

    @Override
    public LbqWrapper<T> from(Integer from) {
        this.from = from;
        return this.typedThis;
    }

    @Override
    public LbqWrapper<T> size(Integer size) {
        this.size = size;
        return this.typedThis;
    }

    @Override
    public LbqWrapper<T> limit(Integer m) {
        this.size = m;
        return this.typedThis;
    }

    @Override
    public LbqWrapper<T> limit(Integer m, Integer n) {
        this.from = m;
        this.size = n;
        return this.typedThis;
    }

    /**
     * SELECT 部分 SQL 设置
     *
     * @param columns 查询字段
     */
    @SafeVarargs
    @Override
    public final LbqWrapper<T> select(SFunction<T, ?>... columns) {
        if (ArrayUtils.isNotEmpty(columns)) {
            setProjection(Projections.include(Arrays.stream(columns).map(FieldUtils::getFieldNameNotConvertId).toArray(String[]::new)));
        }
        return this.typedThis;
    }

    @Override
    public LbqWrapper<T> select(String... columns) {
        setProjection(Projections.include(columns));
        return this.typedThis;
    }

    @Override
    public LbqWrapper<T> select(Predicate<TableFieldInfo> predicate) {
        return select(this.getEntityClass(), predicate);
    }

    /**
     * 过滤查询的字段信息(主键除外!)
     *
     * @param predicate 过滤方式
     * @return this
     */
    @Override
    public LbqWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
        if (entityClass == null) {
            entityClass = getEntityClass();
        } else {
            setEntityClass(entityClass);
        }
        Assert.notNull(entityClass, "entityClass can not be null");
        setProjection(Projections.include(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate)));
        return this.typedThis;
    }

    /**
     * 用于生成嵌套 sql
     */
    @Override
    protected LbqWrapper<T> instance() {
        return new LbqWrapper<>(getEntity(), getEntityClass());
    }

}
